package com.smedi.ismedi.personnel.core.application.service.impl;

import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSONObject;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.smedi.ismedi.personnel.core.application.service.SignatureApplicationService;
import com.smedi.ismedi.personnel.core.domain.aggregatemodel.Signature;
import com.smedi.ismedi.personnel.core.domain.repository.SignatureTemporaryRepository;
import com.smedi.ismedi.personnel.core.domain.service.PersonDomainService;
import com.smedi.ismedi.personnel.core.domain.service.SignatureDomainService;
import com.smedi.ismedi.personnel.core.infrastructure.constant.ConstantField;
import com.smedi.ismedi.personnel.core.infrastructure.constant.CustomError;
import com.smedi.ismedi.personnel.core.port.adapter.service.FdfsClientService;
import com.smedi.ismedi.web.starter.exception.LogicException;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.util.Date;

/**
 * @Author: xulinjun
 * @Date: 2021-6-9 11:49
 */
@Slf4j
@Service
@AllArgsConstructor
class SignatureApplicationServiceImpl implements SignatureApplicationService {
    private final FdfsClientService fdfsClientService;

    private final SignatureDomainService signatureDomainService;

    private final SignatureTemporaryRepository signatureTemporaryRepository;

    private final PersonDomainService personDomainService;

    @Override
    public String uploadSignature(MultipartFile file) {
        try {
            StorePath storePath = fdfsClientService.uploadFileStream(file.getInputStream(), file.getOriginalFilename());
            String signatureUUID = IdUtil.simpleUUID(); // 生成唯一的uuid

            // 将对象存储到Redis，用于监控，防止有过多作废的照片信息
            String key = ConstantField.signatureTempPath + signatureUUID + ConstantField.split + storePath.getGroup() + ConstantField.split + storePath.getPath();
            signatureTemporaryRepository.doInsertTempPath(key, JSONObject.toJSONString(storePath), ConstantField.signatureTempLive);

            return signatureUUID;
        } catch (Exception e) {
            throw LogicException.raise(CustomError.FDFS_UPLOAD_ERROR, e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void uploadSignatureAndSave(MultipartFile file, Long personId) {
        if (personDomainService.isAvailable(personId)) {
            try {
                StorePath storePath = fdfsClientService.uploadFileStream(file.getInputStream(), file.getOriginalFilename());
                signatureDomainService.saveSignature(storePath, personId);
            } catch (Exception e) {
                throw LogicException.raise(CustomError.FDFS_UPLOAD_ERROR, e);
            }
        } else {
            throw LogicException.raise(CustomError.PERSON_NOT_EXIST);
        }
    }

    @Override
    public void dropTempSignature(String group, String path) {
        fdfsClientService.deleteFile(group, path);
    }

    @Override
    public Signature downloadSignature(String signatureUUID) {
        Signature signature = signatureDomainService.getSignature(signatureUUID);
        return getFileFromFdfs(signature);
    }

    @Override
    public Signature downloadSignatureByPersonId(Long personId) {
        Signature signature = signatureDomainService.getSignatureByPersonId(personId);
        return getFileFromFdfs(signature);
    }

    /**
     * 从fdfs下载文件
     *
     * @param signature
     * @return
     */
    private Signature getFileFromFdfs(Signature signature) {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletResponse response = servletRequestAttributes.getResponse();

        // 下载文件
        String fileName = new Date().getTime() + signature.getFilePath().substring(signature.getFilePath().lastIndexOf("."));
        byte[] bytes = fdfsClientService.downloadFile(response, signature.getFileGroup(), signature.getFilePath(), fileName);

        return signature.setFileName(fileName).setBytes(bytes);
    }
}
